home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / IFC_112 / netscape / util / BariumArchiveLoader.java < prev    next >
Encoding:
Text File  |  1999-05-28  |  13.4 KB  |  417 lines  |  [TEXT/CWIE]

  1. // BariumArchiveLoader.java
  2. // By Ned Etcode
  3. // Copyright 1995, 1996, 1997 Netscape Communications Corp.  All rights reserved.
  4.  
  5. package netscape.util;
  6.  
  7. import java.io.*;
  8.  
  9. /** This is just for migration purposes.
  10.   * @private
  11.   */
  12. public class BariumArchiveLoader {
  13.     static final String classVersionsKey = "classVersions";
  14.     static final String classTablesKey = "classTables";
  15.     static final String fieldNamesKey = "fieldNames";
  16.     static final String fieldTypesKey = "fieldTypes";
  17.     static final String instancesKey = "instances";
  18.     static final String classNameKey = "class";
  19.     static final String rootInstancesKey = "rootInstances";
  20.  
  21.     Archive archive;
  22.     Hashtable archiveDict;
  23.     Hashtable allVersions;
  24.  
  25.     IdHashtable idForName;
  26.     String nameForId[];
  27.  
  28.     public BariumArchiveLoader(Archive archive) {
  29.         super();
  30.         this.archive = archive;
  31.     }
  32.  
  33.     public void readASCII(InputStream in) throws CodingException,
  34.         DeserializationException, IOException {
  35.         Deserializer deserializer = null;
  36.  
  37.         if( in instanceof Deserializer) {
  38.             deserializer = (Deserializer) in;
  39.         }
  40.  
  41.  
  42.         // While reading an ASCII archive we need to maintain a mapping
  43.         // between instance "names" in the ASCII file, and the archive ids for
  44.         // those names.
  45.  
  46.         idForName = new IdHashtable(true);
  47.  
  48.         // Read in the ASCII archive file.  If there are any syntax errors in
  49.         // the file this will throw a DeserializationException.  We can't
  50.         // really add more useful error information to that at this point.
  51.  
  52.         if( deserializer == null )
  53.             deserializer = new Deserializer(in);
  54.         archiveDict = (Hashtable)deserializer.readObject();
  55.  
  56.         // Load the pieces of the archive file.
  57.  
  58.         loadVersions();
  59.         loadClassTables();
  60.         loadInstanceData();
  61.         loadRoots();
  62.     }
  63.  
  64.     void loadVersions() {
  65.         Hashtable versionDict;
  66.         Enumeration classNameEnum;
  67.         String className, versionString;
  68.         int version;
  69.  
  70.         versionDict = (Hashtable)archiveDict.get(classVersionsKey);
  71.         if (versionDict == null)
  72.             return;
  73.  
  74.         allVersions = new Hashtable(versionDict.count());
  75.         classNameEnum = versionDict.keys();
  76.  
  77.         while (classNameEnum.hasMoreElements()) {
  78.             className = (String)classNameEnum.nextElement();
  79.             versionString = (String)versionDict.get(className);
  80.             version = Integer.parseInt(versionString);
  81.             allVersions.put(className, new Integer(version));
  82.         }
  83.     }
  84.  
  85.     void loadClassTables() throws CodingException {
  86.         Hashtable allTablesDict, tableDict;
  87.         Enumeration classNameEnum;
  88.         String className;
  89.         Object fieldNamesArray[], fieldTypesArray[];
  90.         String fieldNames[];
  91.         byte fieldTypes[];
  92.         ClassTable table;
  93.         int i, count;
  94.         ClassInfo info;
  95.  
  96.         // Get the information for each of the class tables.  It is not
  97.         // immediately an error to have no class tables, but if there are
  98.         // instances in the archive they will have no place to go and an
  99.         // exception will be thrown during loadInstanceData().
  100.  
  101.         allTablesDict = (Hashtable)archiveDict.get(classTablesKey);
  102.         if (allTablesDict == null)
  103.             return;
  104.  
  105.         classNameEnum = allTablesDict.keys();
  106.  
  107.         while (classNameEnum.hasMoreElements()) {
  108.             className = (String)classNameEnum.nextElement();
  109.             tableDict = (Hashtable)allTablesDict.get(className);
  110.  
  111.             fieldNamesArray = (Object[])tableDict.get(fieldNamesKey);
  112.             fieldNames = new String[fieldNamesArray.length];
  113.             System.arraycopy(fieldNamesArray, 0, fieldNames, 0, fieldNames.length);
  114.  
  115.             fieldTypesArray = (Object[])tableDict.get(fieldTypesKey);
  116.             fieldTypes = fieldTypesForNames(fieldTypesArray);
  117.  
  118.             info = new ClassInfo(className);
  119.  
  120.             count = fieldNames.length;
  121.             for (i = 0; i < count; i++) {
  122.                 info.addField(fieldNames[i], fieldTypes[i]);
  123.             }
  124.  
  125.             // Take a guess at the versions.
  126.             guessAtVersions(className, info);
  127.  
  128.             table = new ClassTable(archive, info);
  129.             archive.addClassTable(table);
  130.         }
  131.     }
  132.  
  133.     void guessAtVersions(String className, ClassInfo info) {
  134.         Class cls;
  135.         Vector classNames;
  136.         int i;
  137.         Integer version;
  138.  
  139.         version = (Integer)allVersions.get(className);
  140.         if (version != null)
  141.             info.addClass(className, version.intValue());
  142.  
  143.         classNames = new Vector();
  144.  
  145.         try {
  146.             cls = Class.forName(className);
  147.             while (cls != null) {
  148.                 classNames.addElement(cls.getName());
  149.                 cls = cls.getSuperclass();
  150.             }
  151.         } catch (ClassNotFoundException e) {
  152.             System.err.println("unable to find class: " + className);
  153.             return;
  154.         }
  155.  
  156.         // skip element 0 since we did that up front.
  157.  
  158.         i = classNames.count();
  159.         while (--i > 0) {
  160.             className = (String)classNames.elementAt(i);
  161.             version = (Integer)allVersions.get(className);
  162.             if (version != null)
  163.                 info.addClass(className, version.intValue());
  164.         }
  165.     }
  166.  
  167.     static byte[] fieldTypesForNames(Object fieldTypesArray[])
  168.         throws CodingException {
  169.  
  170.         int i, count;
  171.         byte fieldTypes[];
  172.         String typeName;
  173.  
  174.         count = fieldTypesArray.length;
  175.         fieldTypes = new byte[count];
  176.  
  177.         for (i = 0; i < count; i++) {
  178.             typeName = (String)fieldTypesArray[i];
  179.             fieldTypes[i] = typeForName(typeName);
  180.         }
  181.  
  182.         return fieldTypes;
  183.     }
  184.  
  185.     static byte typeForName(String typeName) throws CodingException {
  186.         typeName = typeName.toLowerCase();
  187.  
  188.         if (typeName.equals("boolean"))
  189.             return Codable.BOOLEAN_TYPE;
  190.         else if (typeName.equals("byte"))
  191.             return Codable.BYTE_TYPE;
  192.         else if (typeName.equals("short"))
  193.             return Codable.SHORT_TYPE;
  194.         else if (typeName.equals("int"))
  195.             return Codable.INT_TYPE;
  196.         else if (typeName.equals("long"))
  197.             return Codable.LONG_TYPE;
  198.         else if (typeName.equals("float"))
  199.             return Codable.FLOAT_TYPE;
  200.         else if (typeName.equals("double"))
  201.             return Codable.DOUBLE_TYPE;
  202.         else if (typeName.equals("string"))
  203.             return Codable.STRING_TYPE;
  204.         else if (typeName.equals("byte_array"))
  205.             return Codable.BYTE_ARRAY_TYPE;
  206.         else if (typeName.equals("object"))
  207.             return Codable.OBJECT_TYPE;
  208.         else if (typeName.equals("object_array"))
  209.             return Codable.OBJECT_ARRAY_TYPE;
  210.         else
  211.             throw new CodingException("unknown type name: " + typeName);
  212.     }
  213.  
  214.     void loadInstanceData() throws CodingException {
  215.         Hashtable allInstancesDict, instanceDict;
  216.         Enumeration nameEnum;
  217.         String name, className;
  218.         ClassTable table;
  219.         int id, row;
  220.  
  221.         allInstancesDict = (Hashtable)archiveDict.get(instancesKey);
  222.         if (allInstancesDict == null)
  223.             return;
  224.  
  225.         // In the ASCII version of the archive we need to make two passes over
  226.         // the instances.  The first pass creates a row for each instance and
  227.         // builds the name to id mapping.
  228.  
  229.         nameEnum = allInstancesDict.keys();
  230.  
  231.         while (nameEnum.hasMoreElements()) {
  232.             name = (String)nameEnum.nextElement();
  233.             instanceDict = (Hashtable)allInstancesDict.get(name);
  234.  
  235.             if (idForName.get(name) != IdHashtable.NOT_FOUND)
  236.                 throw new CodingException("duplicate instance name: "+name);
  237.  
  238.             className = (String)instanceDict.get(classNameKey);
  239.             if (className == null || className.equals(""))
  240.                 throw new CodingException(
  241.                     "missing className for instance: " + name);
  242.  
  243.             table = archive.classTableForName(className);
  244.             if (table == null)
  245.                 throw new CodingException("bad class name for instance: " +
  246.                     name);
  247.  
  248.             id = table.newIdentifier();
  249.             idForName.putKnownAbsent(name, id);
  250.         }
  251.  
  252.         // The second pass over the instances actually loads the data for each
  253.         // instance into the row.
  254.  
  255.         nameEnum = allInstancesDict.keys();
  256.         while (nameEnum.hasMoreElements()) {
  257.             name = (String)nameEnum.nextElement();
  258.             id = idForName.get(name);
  259.             table = archive.tableForId[id];
  260.             row = archive.rowForId[id];
  261.             instanceDict = (Hashtable)allInstancesDict.get(name);
  262.             loadRow(table, row, instanceDict);
  263.         }
  264.     }
  265.  
  266.     void loadRow(ClassTable table, int row, Hashtable instanceDict)
  267.         throws CodingException {
  268.  
  269.         int i;
  270.         Object value;
  271.  
  272.         for (i = 0; i < table.fieldCount; i++) {
  273.             value = instanceDict.get(table.fieldNames[i]);
  274.             if (value instanceof Object[])
  275.                 setColumnFromArray(table, row, i, (Object[])value);
  276.             else if ((value instanceof String) && !((String)value).equals(""))
  277.                 setColumnFromString(table, row, i, (String)value);
  278.         }
  279.     }
  280.  
  281.     void setColumnFromArray(ClassTable table, int row, int column,
  282.         Object[] value) throws CodingException {
  283.  
  284.         int i, id;
  285.         int array[];
  286.  
  287.         if (table.fieldTypes[column] != Codable.OBJECT_ARRAY_TYPE)
  288.             throw new CodingException("bad data for field " +
  289.                 table.fieldNames[column]);
  290.  
  291.         array = new int[value.length];
  292.  
  293.         for (i = 0; i < array.length; i++) {
  294.             id = idForName.get(value[i]);
  295.             array[i] = id;
  296.         }
  297.  
  298.         table.setIdentifierArrayAt(row, column, array);
  299.     }
  300.  
  301.     void setColumnFromString(ClassTable table, int row, int column,
  302.         String value) throws NumberFormatException, CodingException {
  303.  
  304.         switch (table.fieldTypes[column]) {
  305.             case Codable.BOOLEAN_TYPE:
  306.                 if (value.equalsIgnoreCase("true"))
  307.                     table.setBooleanAt(row, column, true);
  308.                 else if (value.equalsIgnoreCase("false"))
  309.                     table.setBooleanAt(row, column, false);
  310.                 else
  311.                     throw new CodingException("Invalid boolean value");
  312.                 break;
  313.             case Codable.BYTE_TYPE:
  314.                 table.setByteAt(row, column, (byte)Integer.parseInt(value));
  315.                 break;
  316.             case Codable.SHORT_TYPE:
  317.                 table.setShortAt(row, column, (short)Integer.parseInt(value));
  318.                 break;
  319.             case Codable.INT_TYPE:
  320.                 table.setIntAt(row, column, Integer.parseInt(value));
  321.                 break;
  322.             case Codable.LONG_TYPE:
  323.                 table.setLongAt(row, column, Long.parseLong(value));
  324.                 break;
  325.             case Codable.FLOAT_TYPE:
  326.                 table.setFloatAt(row, column,
  327.                     Float.valueOf(value).floatValue());
  328.                 break;
  329.             case Codable.DOUBLE_TYPE:
  330.                 table.setDoubleAt(row, column,
  331.                     Double.valueOf(value).doubleValue());
  332.                 break;
  333.             case Codable.STRING_TYPE:
  334.                 table.setStringAt(row, column, value);
  335.                 break;
  336.             case Codable.BYTE_ARRAY_TYPE:
  337.                 table.setByteArrayAt(row, column, bytesFromString(value));
  338.                 break;
  339.             case Codable.OBJECT_TYPE:
  340.                 table.setIdentifierAt(row, column, idForName.get(value));
  341.                 break;
  342.             default:
  343.                 throw new CodingException("unknown type " +
  344.                     table.fieldTypes[column]);
  345.         }
  346.     }
  347.  
  348.     byte[] bytesFromString(String value) {
  349.         int i, count, nibble, outCount;
  350.         char ch;
  351.         byte buf[], tmp[];
  352.  
  353.         if (value == null || value.equals(""))
  354.             return null;
  355.  
  356.         count = value.length();
  357.         buf = new byte[count / 2 + 1];
  358.         i = 0;
  359.         outCount = 0;
  360.  
  361.         while (i < count) {
  362.             while (i < count) {
  363.                 ch = value.charAt(i++);
  364.                 if (Character.isSpace(ch))
  365.                     continue;
  366.  
  367.                 if (i >= count)
  368.                     throw new NumberFormatException("bad byte string");
  369.  
  370.                 nibble = nibbleForHexChar(ch);
  371.                 ch = value.charAt(i++);
  372.                 buf[outCount++] = (byte)((nibble << 4) + nibbleForHexChar(ch));
  373.             }
  374.         }
  375.  
  376.         tmp = new byte[outCount];
  377.         System.arraycopy(buf, 0, tmp, 0, outCount);
  378.  
  379.         return tmp;
  380.     }
  381.  
  382.     int nibbleForHexChar(char ch) {
  383.         if (ch >= '0' && ch <= '9')
  384.             return ch - '0';
  385.         else if (ch >= 'a' && ch <= 'f')
  386.             return ch - 'a' + 10;
  387.         else if (ch >= 'A' && ch <= 'F')
  388.             return ch - 'A' + 10;
  389.  
  390.         throw new NumberFormatException("bad byte string");
  391.     }
  392.  
  393.     void loadRoots() throws CodingException {
  394.         int i, id;
  395.         Object rootsArray[];
  396.         String name;
  397.  
  398.         rootsArray = (Object[])archiveDict.get(rootInstancesKey);
  399.  
  400.         if (rootsArray == null || rootsArray.length == 0)
  401.             throw new CodingException("no root instances");
  402.  
  403.         for (i = 0; i < rootsArray.length; i++) {
  404.             name = (String)rootsArray[i];
  405.             if (name == null || name.equals(""))
  406.                 id = 0;
  407.             else
  408.                 id = idForName.get(name);
  409.  
  410.             if (id == 0)
  411.                 throw new CodingException("unknown root instance " + name);
  412.  
  413.             archive.addRootIdentifier(id);
  414.         }
  415.     }
  416. }
  417.